package com.penghaisoft.microwms.common.aspect;

import com.alibaba.fastjson.JSONObject;
import com.penghaisoft.microwms.common.Constant;
import com.penghaisoft.microwms.common.util.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * zhangx
 * 监控切片
 */
@Slf4j
@Aspect
@Component
public class RestControllerAspect {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
    public void restController() {
      //找到被RestController注解过的类
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void requestMapping() {
      //找到被RequestMapping注解过的方法
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void getMapping() {
      //找到被GetMapping注解过的方法
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
    public void postMapping() {
      //找到被PostMapping注解过的方法
    }

    /**
     * 获取restController的请求参数、处理异常、返回结果
     * @param joinPoint ProceedingJoinPoint
     * @return Object
     * @throws Throwable 异常抛出
     */
    @Around("(restController() && requestMapping()) || (restController() && getMapping()) || (restController() && postMapping())")
    public Object restControllerAspect(ProceedingJoinPoint joinPoint) throws Throwable {
      Date date = new Date();
      String keyPredix = "monitor:"+Constant.sdfYMD.format(date)+":";
//      切入到controller拿到url
      HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
      String url = request.getRequestURI();
      String k = url.substring(1);
      String key = keyPredix + k;
      log.info("切面切入==========="+url);
      Object proceedResult = null;
      Boolean hasError = false;
  //    log.info("rest-request:[{}]", getWebRequest(joinPoint));
      long begin = System.currentTimeMillis();
      try {
        proceedResult = joinPoint.proceed(joinPoint.getArgs());
      } catch (Exception e) {
        log.error("exception message:[{}]", e.getMessage());
        long end = System.currentTimeMillis();
        hasError = true;
        redisTemplate.opsForZSet().add(key+":0",String.valueOf(begin)+CommonUtils.generateShortUuid(),end - begin);
        throw e;
      } finally {
        if (!hasError) {
          long end = System.currentTimeMillis();
          log.info("consume {} ms & response-result:[{}]", end - begin,
                  JSONObject.toJSONString(proceedResult));
          redisTemplate.opsForZSet().add(key+":1",String.valueOf(begin)+CommonUtils.generateShortUuid(),end - begin);
        }
      }
      return proceedResult;
    }

    /**
     * 获取请求参数
     * @param joinPoint ProceedingJoinPoint
     * @return String
     */
  //  private String getWebRequest(ProceedingJoinPoint joinPoint) {
  //    String className = joinPoint.getTarget().getClass().getSimpleName();
  //    String methodName = joinPoint.getSignature().getName();
  //    Object[] args = joinPoint.getArgs();
  //    return className + "-" + methodName + "-" + StringUtil.getWebArrayString(args);
  //  }

}